#include "ads8689_driver.h">
/* SPI设备驱动框架 */
/* 驱动 ADS8689 AD采集模块 */
/* 设备树SPI使用引脚
MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK	-----> SCLK
MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO		-----> MISO
MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI		-----> MOSI
 */

struct _spi_dev adc_dev;

static int adc_open(struct inode *inode, struct file *file)
{
    file->private_data = &adc_dev;
    return 0;
}
static ssize_t adc_read(struct file *file, char __user *buff, size_t size, loff_t *lenth)
{

    return 0;
}
static ssize_t adc_write(struct file *file, const char __user *buff, size_t size, loff_t *lenth)
{
    int retvalue;
    uint8_t cmd;
    retvalue = copy_from_user(&cmd, buff, size);
    if (retvalue < 0)
    {
        printk("kernel write is faispi\n");
    }
    return 0;
}
static int adc_release(struct inode *inode, struct file *file)
{
    return 0;
}
static struct file_operations adc_fops =
    {
        .owner = THIS_MODULE,
        .open = adc_open,
        .write = adc_write,
        .read = adc_read,
        .release = adc_release,
};

/*
驱动初始化流程
1、分配cdev
    1.1 静态分配
    1.2 动态分配
2、初始化cdev cdev_init()
3、注册 cdev cdev_add()
4、创建类 class_creat()
5、创建设备 device_creat()
 */
static int adc_probe(struct spi_device *spi)
{
    int ret = 0;
    /* 注册字符设备驱动 */
    // 1、创建设备号
    if (adc_dev.major) //静态分配设备号
    {
        adc_dev.devid = MKDEV(adc_dev.major, 0);
        register_chrdev_region(adc_dev.devid, spi_dev_num, spi_dve_name);
    }
    else
    {
        alloc_chrdev_region(&adc_dev.devid, 0, spi_dev_num, spi_dve_name); //动态申请设备号
        adc_dev.major = MAJOR(adc_dev.devid);                              //获取主设备号
        adc_dev.minor = MINOR(adc_dev.devid);                              //获取次设备号
    }
    printk("adc_dev major=%d,minor=%d\r\n", adc_dev.major, adc_dev.minor);
    // 2、 初始化cdev
    cdev_init(&adc_dev.cdev, &adc_fops);
    // 3、 注册cdev
    cdev_add(&adc_dev.cdev, adc_dev.devid, spi_dev_num);
    // 4、 创建类
    adc_dev.class = class_create(THIS_MODULE, spi_dve_name);
    if (adc_dev.class == NULL)
    {
        printk("class creat failed\n");
    }
    // 5、创建设备
    adc_dev.device = device_create(adc_dev.class, NULL, adc_dev.devid, NULL, spi_dve_name);
    if (adc_dev.device == NULL)
    {
        printk("device creat failed\n");
        return -ENAVAIL;
    }
    /*获取父节点 注意 spi->dev.of_node 就是当前匹配到的spi ads模块的子节点*/
    adc_dev.parent_node = of_get_parent(spi->dev.of_node); //获取当前子节点的父节点。
    if (adc_dev.parent_node == NULL)
    {
        printk("parent node is null\n");
        return -ENAVAIL;
    }
    /* 获取父节点下属性中的引脚 */
    /* 1、获取父节点下的 “cs-gpio"属性中的引脚  cs-gpio 属性是在父节点下*/
    adc_dev.cs_gpio = of_get_named_gpio(adc_dev.parent_node, "cs-gpio", 0);
    if (adc_dev.cs_gpio < 0)
    {
        printk("cs-gpio is error\n");
        return -ENAVAIL;
    }
    /*2、获取父节点下的 “rvs-gpio"属性中的引脚  rvs-gpio 属性是在父节点下*/
    adc_dev.rvs_gpio = of_get_named_gpio(adc_dev.parent_node, "rvs-gpio", 0);
    if (adc_dev.rvs_gpio < 0)
    {
        printk("rvs_gpio is error\n");
        return -ENAVAIL;
    }
    /*3、获取父节点下的 “rest-gpio"属性中的引脚  rest-gpio 属性是在父节点下*/
    adc_dev.rvs_gpio = of_get_named_gpio(adc_dev.parent_node, "rest-gpio", 0);
    if (adc_dev.rest_gpio < 0)
    {
        printk("rest-gpio is error\n");
        return -ENAVAIL;
    }
    /* 申请GPIO引脚 */
    /*1、申请 CS片选引脚 */
    ret = gpio_request(adc_dev.cs_gpio, "adc-cs-gpio");
    if (ret)
    {
        printk("cs-gpio request failed\n");
        return -ENAVAIL;
    }
    /*2、申请 rvs 输入信号 引脚 */
    ret = gpio_request(adc_dev.rvs_gpio, "adc-rvs-gpio");
    if (ret)
    {
        printk("rvs-gpio request failed\n");
        return -ENAVAIL;
    }
    /*3、 申请 rest 复位引脚 */
    ret = gpio_request(adc_dev.rest_gpio, "adc-rest-gpio");
    if (ret)
    {
        printk("rest-gpio request failed\n");
        return -ENAVAIL;
    }
    /* 配置引脚功能 */
    /* 配置 CS片选引脚为输出，初始化为高电平 */
    ret = gpio_direction_output(adc_dev.cs_gpio, 1);
    if (ret)
    {
        printk("set cs-gpio output failed\n");
        return -ENAVAIL;
    }
    /* 配置  rvs 引脚为输入 */
    ret = gpio_direction_input(adc_dev.rvs_gpio);
    if (ret)
    {
        printk("set rvs-gpio  failed\n");
        return -ENAVAIL;
    }
    /* 配置 rest复位引脚为输出，初始化为高电平 */
    ret = gpio_direction_output(adc_dev.rest_gpio, 1);
    if (ret)
    {
        printk("set rest-gpio output failed\n");
        return -ENAVAIL;
    }
    /* 初始化 配置SPI */
    spi->mode = SPI_MODE_0;     /*配置 SPI模式MODE0，CPOL=0，CPHA=0 */
    spi_setup(spi);             /* 初始化spi控制器 */
    adc_dev.private_data = spi; //设置私有数据
    return ret;
}
static int adc_remove(struct spi_device *spi)
{
    /* 注销字符设备 */
    cdev_del(&adc_dev.cdev);
    unregister_chrdev_region(adc_dev.devid, spi_dev_num);
    /* 卸载设备时必须先现在 设备，在卸载类，因为卸载设备时需要用到类 */
    device_destroy(adc_dev.class, adc_dev.devid);
    class_destroy(adc_dev.class);
    gpio_free(adc_dev.cs_gpio); //释放GPIO
    gpio_free(adc_dev.rvs_gpio); //释放GPIO
    gpio_free(adc_dev.rest_gpio); //释放GPIO
    return 0;
}
/* 普通匹配列表 */
static struct spi_device_id adc_id[] = {
    {"alientek,ads8689", 0},
    {},
};
/* 设备树匹配列表 */
static struct of_device_id of_match_adc[] = {
    {.compatible = "alientek,ads8689"},
    {},
};
/* SPI设备驱动结构体，需要进行填充 */
struct spi_driver adc_driver = {
    .probe = adc_probe,
    .remove = adc_remove,
    .id_table = adc_id,
    .driver =
        {
            .owner = THIS_MODULE,
            .name = "ADS8689",
            .of_match_table = of_match_adc,
        },
};
static int __init adc_driver_init(void)
{
    spi_register_driver(&adc_driver); //注册驱动框架
    printk("spi init success\n");
    return 0;
}
static void __exit adc_driver_exit(void)
{
    spi_unregister_driver(&adc_driver); //注销驱动框架
    printk("spi exit success\n");
}

module_init(adc_driver_init);
module_exit(adc_driver_exit);
MODULE_LICENSE("GPL");
